package com.miyake.loveviewweb.client.plugin;
import java.util.ArrayList;
import java.util.List;

import com.google.gwt.core.client.GWT;
import com.google.gwt.safehtml.shared.SafeHtmlBuilder;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.HasText;
import com.google.gwt.user.client.ui.Widget;
import com.google.gwt.user.cellview.client.CellTree;
import com.google.gwt.view.client.SingleSelectionModel;
import com.google.gwt.view.client.TreeViewModel;
import com.google.gwt.view.client.ListDataProvider;
import com.google.gwt.view.client.TreeViewModel.NodeInfo;
import com.google.gwt.cell.client.AbstractCell;
import com.google.gwt.cell.client.Cell;
import com.google.gwt.cell.client.TextCell;

public class PluginListEx extends Composite implements HasText {

    private static PluginListExUiBinder uiBinder = GWT
        .create(PluginListExUiBinder.class);

    interface PluginListExUiBinder extends UiBinder<Widget, PluginListEx> {
    }

    public PluginListEx() {
        initWidget(uiBinder.createAndBindUi(this));
        initialize();
    }

    private void initialize() {

    }
    @UiField(provided=true) CellTree cellTree = new CellTree(
        new PluginTreeModel2(), null);

    public PluginListEx(String firstName) {
        initWidget(uiBinder.createAndBindUi(this));
        initialize();
    }

    public void setText(String text) {

    }

    public String getText() {
        return "";
    }
    
    private static class Pluginlist {
        private final String name;
        private final List<String> plugins = new ArrayList<String>();

        public Pluginlist(String name) {
          this.name = name;
        }

        /**
         * Add a song to the Pluginlist.
         * 
         * @param name the name of the song
         */
        public void addPlugin(String name) {
          plugins.add(name);
        }

        public String getName() {
          return name;
        }

        /**
         * Return the list of songs in the Pluginlist.
         */
        public List<String> getPlugins() {
          return plugins;
        }
      }

      /**
       * A composer of classical music.
       */
      private static class PluginProvider {
        private final String name;
        private final List<Pluginlist> pluginlists = new ArrayList<Pluginlist>();

        public PluginProvider(String name) {
          this.name = name;
        }

        /**
         * Add a Pluginlist to the composer.
         * 
         * @param Pluginlist the Pluginlist to add
         */
        public Pluginlist addPluginlist(Pluginlist Pluginlist) {
          pluginlists.add(Pluginlist);
          return Pluginlist;
        }

        public String getName() {
          return name;
        }

        /**
         * Return the rockin' Pluginlist for this composer.
         */
        public List<Pluginlist> getPluginlists() {
          return pluginlists;
        }
      }

      private static class PluginComposite {
          private List<PluginComposite> subNodes = new ArrayList<PluginComposite>();
          private String name;
        /**
         * @return the name
         */
        public String getName() {
            return name;
        }
        public PluginComposite(String name) {
            super();
            this.name = name;
        }
        /**
         * @param name the name to set
         */
        public void setName(String name) {
            this.name = name;
        }
        
        public void addSubNode(PluginComposite c) {
            subNodes.add(c);
        }
        
        public List<PluginComposite> getSubNodes() {
            return subNodes;
        }
      }
      
      private static List<PluginComposite> rootNodes;
      
      private static class PluginTreeModel2 implements TreeViewModel {
          private final SingleSelectionModel<String> selectionModel = new SingleSelectionModel<String>();
          
          public PluginTreeModel2() {
              
              rootNodes = new ArrayList<PluginComposite>();
              
              { //OSA
                  PluginComposite osaRoot = new PluginComposite("Open OSA Project");
                  osaRoot.addSubNode(new PluginComposite("MS9740A XML Parser"));
                  osaRoot.addSubNode(new PluginComposite("MS9740A CSV Parser"));
                  osaRoot.addSubNode(new PluginComposite("WDM Applucation"));
                  rootNodes.add(osaRoot);
              }
              rootNodes.add(new PluginComposite("Open OTDR Project"));
              
              { // Anritsu
                  PluginComposite anritsuRoot = new PluginComposite("Anritsu Corporation");
                  rootNodes.add(anritsuRoot);
                  
                  { // OSA
                      PluginComposite osaNode = new PluginComposite("OSA");
                      anritsuRoot.addSubNode(osaNode);
                      osaNode.addSubNode(new PluginComposite("MS9740A XML File Parser"));
                      osaNode.addSubNode(new PluginComposite("MS9740A CSV File Parser"));
                      osaNode.addSubNode(new PluginComposite("MS9740A WDM Application"));
                      osaNode.addSubNode(new PluginComposite("MS9740A EDFA Application"));
                  }
                  { // OTDR
                      PluginComposite otdrNode = new PluginComposite("OTDR");
                      anritsuRoot.addSubNode(otdrNode);  
                      otdrNode.addSubNode(new PluginComposite("SR4731 File Parser"));
                      otdrNode.addSubNode(new PluginComposite("GR196 File Parser"));
                      otdrNode.addSubNode(new PluginComposite("Event Search Application"));
                  }
              }
              
              rootNodes.add(new PluginComposite("EXFO"));
              rootNodes.add(new PluginComposite("Agilent"));
              rootNodes.add(new PluginComposite("Yokogawa"));
              rootNodes.add(new PluginComposite("National Instruments"));
          }
          
        public <T> NodeInfo<?> getNodeInfo(T value) {
            if (value == null) {
                // LEVEL 0.
                // We passed null as the root value. Return the composers.
            
                // Create a data provider that contains the list of composers.
                ListDataProvider<PluginComposite> dataProvider = new ListDataProvider<PluginComposite>(
                    rootNodes);
            
                // Create a cell to display a composer.
                Cell<PluginComposite> cell = new AbstractCell<PluginComposite>() {
            
                    @Override
                    public void render(com.google.gwt.cell.client.Cell.Context context,
                            PluginComposite value, SafeHtmlBuilder sb) {
                        if (value != null) {
                            sb.appendEscaped(value.getName());
                          }
                    }
                };
        
                // Return a node info that pairs the data provider and the cell.
                return new DefaultNodeInfo<PluginComposite>(dataProvider, cell);
            } 
            else if (value instanceof PluginComposite) {
                // LEVEL 1.
                // We want the children of the composer. Return the Pluginlists.
                if (((PluginComposite) value).getSubNodes().size() == 0) {
                    return null;
                }
                else if (((PluginComposite) value).getSubNodes().get(0).getSubNodes().size() > 0) {
                    ListDataProvider<PluginComposite> dataProvider = new ListDataProvider<PluginComposite>(
                            ((PluginComposite) value).getSubNodes());
                    Cell<PluginComposite> cell = new AbstractCell<PluginComposite>() {
                      @Override
                      public void render(Context context, PluginComposite value, SafeHtmlBuilder sb) {
                        if (value != null) {
                          sb.appendEscaped(value.getName());
                        }
                      }
                    };
                    return new DefaultNodeInfo<PluginComposite>(dataProvider, cell);                    
                }
                else {
                    // LEVEL 2 - LEAF.
                    // We want the children of the Pluginlist. Return the songs.
                    List<String> leafs = new ArrayList<String>();
                    for (PluginComposite c : ((PluginComposite) value).getSubNodes()) {
                        leafs.add(c.getName());
                    }
                    ListDataProvider<String> dataProvider = new ListDataProvider<String>(leafs);

                    // Use the shared selection model.
                    return new DefaultNodeInfo<String>(dataProvider, new TextCell(),
                        selectionModel, null);
                } 
            }
            return null;
        }
        
        public boolean isLeaf(Object value) {
            if (value instanceof String) {
                return true;
            }
           // if (value != null && ((PluginComposite)value).getSubNodes().size() == 0) {
           //     return true;
           // }
            return false;
        }
          
      }
      
      /**
       * The model that defines the nodes in the tree.
       */
      private static class PluginTreeModel implements TreeViewModel {

        private final List<PluginProvider> providers;

        /**
         * This selection model is shared across all leaf nodes. A selection model
         * can also be shared across all nodes in the tree, or each set of child
         * nodes can have its own instance. This gives you flexibility to determine
         * how nodes are selected.
         */
        private final SingleSelectionModel<String> selectionModel = new SingleSelectionModel<String>();

        public PluginTreeModel() {
          // Create a database of information.
            providers = new ArrayList<PluginProvider>();

            {
                PluginProvider openotdr = new PluginProvider("Open OTDR Project");
                providers.add(openotdr);            
            }
            
            {
                PluginProvider openosa = new PluginProvider("Open OSA Project");
                providers.add(openosa);            
            }
            
          // Add compositions by Beethoven.
          {
            PluginProvider anritsu = new PluginProvider("Anritsu");
            providers.add(anritsu);

            Pluginlist fileParser = anritsu.addPluginlist(new Pluginlist("File Parser"));
            fileParser.addPlugin("MS9740A XML");
            fileParser.addPlugin("MS9740A CSV");
            fileParser.addPlugin("OTDR SR4731");
            fileParser.addPlugin("OTDR GR196");

            Pluginlist analysis = anritsu.addPluginlist(new Pluginlist("Analysis"));
            analysis.addPlugin("Threshold");
            analysis.addPlugin("WDM");
            analysis.addPlugin("OTDR Event Search");

            Pluginlist sonatas = anritsu.addPluginlist(new Pluginlist("Sonatas"));
            sonatas.addPlugin("Sonata in A Minor");
            sonatas.addPlugin("Sonata in F Major");

            Pluginlist symphonies = anritsu.addPluginlist(new Pluginlist("Symphonies"));
            symphonies.addPlugin("No. 2 - D Major");
            symphonies.addPlugin("No. 2 - D Major");
          }

          // Add compositions by Brahms.
          {
            PluginProvider exfo = new PluginProvider("EXFO");
            providers.add(exfo);
            Pluginlist concertos = exfo.addPluginlist(new Pluginlist("Concertos"));
            concertos.addPlugin("Violin Concerto");
            concertos.addPlugin("Double Concerto - A Minor");

            Pluginlist quartets = exfo.addPluginlist(new Pluginlist("Quartets"));
            quartets.addPlugin("Piano Quartet No. 1 - G Minor");
            quartets.addPlugin("Piano Quartet No. 2 - A Major");

            Pluginlist sonatas = exfo.addPluginlist(new Pluginlist("Sonatas"));
            sonatas.addPlugin("Two Sonatas for Clarinet - F Minor");
            sonatas.addPlugin("Two Sonatas for Clarinet - E-Flat Major");

            Pluginlist symphonies = exfo.addPluginlist(new Pluginlist("Symphonies"));
            symphonies.addPlugin("No. 1 - C Minor");
            symphonies.addPlugin("No. 2 - D Minor");
          }

          // Add compositions by Mozart.
          {
            PluginProvider agilent = new PluginProvider("Agilent");
            providers.add(agilent);
            Pluginlist concertos = agilent.addPluginlist(new Pluginlist("Concertos"));
            concertos.addPlugin("Piano Concerto No. 12");
            concertos.addPlugin("Piano Concerto No. 17");
          }
        }

        /**
         * Get the {@link NodeInfo} that provides the children of the specified
         * value.
         */
        public <T> NodeInfo<?> getNodeInfo(T value) {
          if (value == null) {
            // LEVEL 0.
            // We passed null as the root value. Return the composers.

            // Create a data provider that contains the list of composers.
            ListDataProvider<PluginProvider> dataProvider = new ListDataProvider<PluginProvider>(
                providers);

            // Create a cell to display a composer.
            Cell<PluginProvider> cell = new AbstractCell<PluginProvider>() {

                @Override
                public void render(com.google.gwt.cell.client.Cell.Context context,
                        PluginProvider value, SafeHtmlBuilder sb) {
                    if (value != null) {
                        sb.appendEscaped(value.getName());
                      }
                }
            };

            // Return a node info that pairs the data provider and the cell.
            return new DefaultNodeInfo<PluginProvider>(dataProvider, cell);
          } else if (value instanceof PluginProvider) {
            // LEVEL 1.
            // We want the children of the composer. Return the Pluginlists.
            ListDataProvider<Pluginlist> dataProvider = new ListDataProvider<Pluginlist>(
                ((PluginProvider) value).getPluginlists());
            Cell<Pluginlist> cell = new AbstractCell<Pluginlist>() {
              @Override
              public void render(Context context, Pluginlist value, SafeHtmlBuilder sb) {
                if (value != null) {
                  sb.appendEscaped(value.getName());
                }
              }
            };
            return new DefaultNodeInfo<Pluginlist>(dataProvider, cell);
          } else if (value instanceof Pluginlist) {
            // LEVEL 2 - LEAF.
            // We want the children of the Pluginlist. Return the songs.
            ListDataProvider<String> dataProvider = new ListDataProvider<String>(
                ((Pluginlist) value).getPlugins());

            // Use the shared selection model.
            return new DefaultNodeInfo<String>(dataProvider, new TextCell(),
                selectionModel, null);
          }

          return null;
        }

        /**
         * Check if the specified value represents a leaf node. Leaf nodes cannot be
         * opened.
         */
        public boolean isLeaf(Object value) {
          // The leaf nodes are the songs, which are Strings.
          if (value instanceof String) {
            return true;
          }
          return false;
        }

      }


}
